using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Xeml.Document;
using System.Linq;

namespace Xid.Controls
{
    public partial class ObservationLayoutCtrl : UserControl
    {
        private Rectangle observationRegion;
        private Rectangle partitionRegion;
        private Rectangle sampleRegion;
        private int thirdPart;


        private int headerHeight = 50;
        private Size observationCtrlSize = new Size(100, 70);
        private Padding observationCtrlPadding = new Padding(4, 3, 1, 3);
        private Size partitionCtrlSize = new Size(100, 75);
        private Padding partitionCtrlPadding = new Padding(1, 3, 1, 3);
        private Size sampleCtrlSize = new Size(100, 30);
        private Padding sampleCtrlPadding = new Padding(1, 3, 4, 3);


        private ObservationPoint obPoint;

        public ObservationPoint ObservationPoint
        {
            get { return obPoint; }
            set
            {
                obPoint = value;
                PopulateCtrls();
                Invalidate();
            }
        }


        // private List<OlC_PartitionCtrl> partitionCtrls = new List<OlC_PartitionCtrl>();
        private Dictionary<OlC_ObservationCtrl, List<OlC_PartitionCtrl>> obCtrlTopartCtrlRel = new Dictionary<OlC_ObservationCtrl, List<OlC_PartitionCtrl>>();
        private Dictionary<OlC_SampleCtrl, List<OlC_PartitionCtrl>> sampleCtrlTopartCtrlRel = new Dictionary<OlC_SampleCtrl, List<OlC_PartitionCtrl>>();


        private void PopulateCtrls()
        {
            //this.Controls.Clear();
            List<Control> toRem = new List<Control>();
            foreach (Control c in this.Controls)
            {
                if (!(c is TableLayoutPanel))
                {
                    toRem.Add(c);
                }
            }
            foreach (Control c in toRem)
            {
                this.Controls.Remove(c);
                c.Dispose();
            }

            obCtrlTopartCtrlRel.Clear();
            sampleCtrlTopartCtrlRel.Clear();
            if (this.ObservationPoint != null)
            {
                int yOffset = headerHeight;
                foreach (Observation ob in this.obPoint.Observations)
                {
                    OlC_ObservationCtrl b = new OlC_ObservationCtrl();
                    b.Observation = ob;
                    b.Size = observationCtrlSize;
                    //b.Text = ob.ObjectIdentifiere.ToString();
                    Rectangle partitionLayoutTect = PopulatePartitionCtrl(b, yOffset, ob);
                    b.Left = observationCtrlPadding.Left;
                    b.Top = partitionLayoutTect.Top + (partitionLayoutTect.Height / 2) - (observationCtrlSize.Height / 2);
                    yOffset = partitionLayoutTect.Bottom;
                    this.Controls.Add(b);
                }
                PopulateSampleCtrls();
            }

        }


        private int mostBottomPoint = 0;
        private Rectangle PopulatePartitionCtrl(OlC_ObservationCtrl obCtrl, int yOffset, Observation ob)
        {
            Rectangle ret = new Rectangle();
            ret.Location = new Point(thirdPart, yOffset);
            ret.Width = thirdPart;
            ret.Height = ob.Partitions.Count * (partitionCtrlSize.Height + partitionCtrlPadding.Top + partitionCtrlPadding.Bottom);

            int yPos = yOffset;
            foreach (Partition p in ob.Partitions)
            {
                OlC_PartitionCtrl b = new OlC_PartitionCtrl();
                b.Partition = p;
                b.Size = this.partitionCtrlSize;
                b.Left = thirdPart + (thirdPart / 2) - (partitionCtrlSize.Width / 2);
                b.Top = yPos + partitionCtrlPadding.Top;
                this.Controls.Add(b);
                //this.partitionCtrls.Add(b);
                yPos = yPos + partitionCtrlSize.Height + partitionCtrlPadding.Top + partitionCtrlPadding.Bottom;
                if (!obCtrlTopartCtrlRel.ContainsKey(obCtrl))
                {
                    obCtrlTopartCtrlRel.Add(obCtrl, new List<OlC_PartitionCtrl>());
                }
                this.obCtrlTopartCtrlRel[obCtrl].Add(b);
            }



            return ret;
        }


        private void PopulateSampleCtrls()
        {
            List<Sample> samples = DocumentHelper.FindAllSamples(this.obPoint).ToList();
            foreach (Sample s in samples)
            {
                OlC_SampleCtrl b = new OlC_SampleCtrl();

                b.Size = sampleCtrlSize;
                int top = int.MaxValue;
  
                int bottom = 0;
                b.Sample = s;
                foreach (Partition p in s.Partitions)
                {
                    foreach (List<OlC_PartitionCtrl> pctrls in this.obCtrlTopartCtrlRel.Values)
                    {
                        foreach (OlC_PartitionCtrl pctrl in pctrls)
                        {
                            if (pctrl.Partition == p)
                            {
                                top = Math.Min(top, pctrl.Top);
                                bottom = Math.Max(bottom, pctrl.Bottom);
                                if (!sampleCtrlTopartCtrlRel.ContainsKey(b))
                                {
                                    sampleCtrlTopartCtrlRel.Add(b, new List<OlC_PartitionCtrl>());
                                }
                                this.sampleCtrlTopartCtrlRel[b].Add(pctrl);
                            }
                        }

                    }
                }

                b.Left = (3 * thirdPart) - sampleCtrlSize.Width - sampleCtrlPadding.Right;
                b.Top = top + (bottom - top) / 2 - (sampleCtrlSize.Height / 2);
            //    b.Top += this.AutoScrollOffset.Y;
                this.Controls.Add(b);

            }



        }



        public ObservationLayoutCtrl()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);

            CalcRegions();
        }

        private void CalcRegions()
        {
          
            this.thirdPart = (this.AutoScrollMinSize.Width-20) / 3;
            observationRegion = new Rectangle(0, 0, thirdPart, this.Height);
            partitionRegion = new Rectangle(thirdPart, 0, thirdPart, this.Height);
            sampleRegion = new Rectangle(2 * thirdPart, 0, thirdPart, this.Height);
        }



        private Size oldSize;
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            //CalcRegions();

            //if (oldSize.Width != this.Size.Width)
            //{
            //    PopulateCtrls();
            //}
            //Invalidate();
            //oldSize = this.Size;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;


            //g.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
            //g.DrawRectangle(Pens.Black, observationRegion);
            //g.DrawRectangle(Pens.Black, partitionRegion);
            //g.DrawRectangle(Pens.Black, sampleRegion);

            using (Pen linePen = new Pen(Color.SteelBlue, 2f))
            {
                foreach (OlC_ObservationCtrl obCtrl in this.obCtrlTopartCtrlRel.Keys)
                {
                    foreach (OlC_PartitionCtrl partCtrl in this.obCtrlTopartCtrlRel[obCtrl])
                    {
                        g.DrawLine(linePen, obCtrl.MiddleRight, partCtrl.MiddleLeft);
                    }
                }

                foreach (OlC_SampleCtrl sampCtrl in this.sampleCtrlTopartCtrlRel.Keys)
                {
                    foreach (OlC_PartitionCtrl partCtrl in this.sampleCtrlTopartCtrlRel[sampCtrl])
                    {
                        g.DrawLine(linePen, sampCtrl.MiddleLeft, partCtrl.MiddleRight);
                    }
                }
            }

            base.OnPaint(e);
        }
    }
}
